﻿using System;
using System.Windows.Forms;
using System.Collections;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;
using Microsoft.CSharp;
using QAHelper.Common;
using WatiNTest;
using Logger;


namespace TestHarness_GUI
{
    public static class TestGenerator
    {
        public static TestCaseStructure testCaseStructure = null;
        public static ArrayList headerList = null;
        public static DataGridView dgv = null;
        public static TreeView treeLogFiles = null;

        
        public static void Generate(string dataFileDir, string logDestDir, string urlToTest)
        {
            DataGridViewRow dgvRow = new DataGridViewRow();
            DataGridViewColumn dgvClm = new DataGridViewColumn();


            int rowIndex = dgv.Rows.Add(dgvRow);
            dgv.Rows[rowIndex].Cells[0].Value = "Initiating Environment";
                        

            string thisDateTime = DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString();
            string testScriptDir = dataFileDir;//Properties.Settings.Default.TEST_SCRIPT_DIRECTORY;
            string traceLogFileName = logDestDir + @"Test_Generation_TraceLog_" + DateTime.Now.ToString("MM_dd_yyyy_hh_mm_ss") + ".log";


            if (!Directory.Exists(Directory.GetParent(logDestDir).Name))
                Directory.CreateDirectory(Directory.GetParent(logDestDir).Name);


            if (!Directory.Exists(logDestDir.Trim()))
                Directory.CreateDirectory(logDestDir.Trim());

            string logDir = logDestDir; //+ DateTime.Now.ToString("MM_dd_yyyy_hh_mm");



            dgvRow = UpdateDataGridView(dgv, dgvRow, rowIndex,"1");
            try
            {
                
                Console.WriteLine("{0} Starting Test Generator for WatiN.............", thisDateTime);
                File.AppendAllText(traceLogFileName, string.Format("{0} Starting Test Generator for WatiN............."+Environment.NewLine, thisDateTime));

                if (!string.IsNullOrEmpty(testScriptDir))
                {

                    rowIndex = dgv.Rows.Add(dgvRow);
                    dgv.Rows[rowIndex].Cells[0].Value = "Reading files from "+testScriptDir;                        

                    string[] fileNames = Directory.GetFiles(testScriptDir);
                    DirectoryInfo directoryInfo = new DirectoryInfo(testScriptDir);
                    
                    FileSystemInfo[] fileInfos = directoryInfo.GetFileSystemInfos();

                    dgvRow = UpdateDataGridView(dgv, dgvRow, rowIndex,"1");

                    int rowIndexFiles = dgv.Rows.Add(dgvRow);
                    dgv.Rows[rowIndexFiles].Cells[0].Value = string.Format("Traversing through  total {0} test script files", fileInfos.Length);

                    foreach (string fileName in fileNames)
                    {
                        string[] extensionArray = fileName.Split('.');
                        string extension = extensionArray[1];
                        if (!extension.Equals("xls"))
                            continue;
                        testCaseStructure = new TestCaseStructure();
                        headerList = new ArrayList();

                        FileInfo fileInfo = new FileInfo(fileName);
                        string className = fileInfo.Name.Replace("_", "").Split('.')[0];

                        if (className.Contains("-"))
                            className = className.Replace("-", "");

                        DataGridViewRow testFileRow = new DataGridViewRow();
                        rowIndex = dgv.Rows.Add(testFileRow);
                        dgv.Rows[rowIndex].Cells[0].Value = string.Format("Reading Test Scenarios from {0}", fileName);


                        Console.WriteLine("\n{0} Reading Test Scenarios from {1}.............", thisDateTime, fileName);
                        File.AppendAllText(traceLogFileName, string.Format(Environment.NewLine+"{0} Reading Test Scenarios from {1}............." + Environment.NewLine, thisDateTime, fileName));

                        ExcelReader reader = new ExcelReader();
                        HtmlLogger logger = new HtmlLogger();

                        testCaseStructure.TestCaseFileName = fileName;
                        testCaseStructure.TestCaseWorkSheetName = "Test_Plan";
                        /*testCaseStructure.TestLogFileName = logDestDir +
                                                            className + "_" +
                                                            DateTime.Now.ToString("MM_dd_yyyy_hh_mm_ss") + ".xls";*/

                        testCaseStructure = reader.ReadInputFromFile(testCaseStructure, out headerList, 10);


                        Console.WriteLine("{0} End of Reading Test Scenarios from {1}.............", thisDateTime, fileName);
                        File.AppendAllText(traceLogFileName, string.Format("{0} End of Reading Test Scenarios from {1}............." + Environment.NewLine, thisDateTime, fileName));

                        dgvRow = UpdateDataGridView(dgv, testFileRow, rowIndex, "1");

                        testFileRow = new DataGridViewRow();
                        rowIndex = dgv.Rows.Add(testFileRow);
                        dgv.Rows[rowIndex].Cells[0].Value = string.Format("Starting Generation of {0}.............", className);
                        Console.WriteLine("{0} Starting Generation of {1}.............", thisDateTime, className);
                        File.AppendAllText(traceLogFileName, string.Format("{0} Starting Generation of {1}............." + Environment.NewLine, thisDateTime, fileName));



                        for (int i = 0; i < testCaseStructure.TestScenarios.Count; i++)
                        {
                            TestScenario scenario = (TestScenario)testCaseStructure.TestScenarios[i];

                            if (!string.IsNullOrEmpty(scenario.SkipExecution))
                            {
                                if (scenario.SkipExecution.Equals("0"))
                                {
                                    if (!string.IsNullOrEmpty(scenario.TestCaseID))
                                    {

                                        Stream s = File.Open(logDestDir + className +".cs", FileMode.Create);
                                        StreamWriter sw = new StreamWriter(s);

                                        #region Initiate Provider and Option
                                        CSharpCodeProvider cscProvider = new CSharpCodeProvider();
                                        CodeGeneratorOptions cop = new CodeGeneratorOptions();
                                        cop.BlankLinesBetweenMembers = true;
                                        cop.BracingStyle = "C";
                                        
                                        ICodeGenerator cscg = cscProvider.CreateGenerator(sw);

                                        #endregion
                                        

                                        #region Create Class Using Statements

                                        CodeSnippetCompileUnit csu = new CodeSnippetCompileUnit("using System.Collections;");
                                        cscg.GenerateCodeFromCompileUnit(csu, sw, cop);
                                        csu = new CodeSnippetCompileUnit("using WatiN.Core;");
                                        cscg.GenerateCodeFromCompileUnit(csu, sw, cop);
                                        csu = new CodeSnippetCompileUnit("using Microsoft.VisualStudio.TestTools.UnitTesting;");
                                        cscg.GenerateCodeFromCompileUnit(csu, sw, cop);
                                        csu = new CodeSnippetCompileUnit("using QAHelper.Common;");
                                        cscg.GenerateCodeFromCompileUnit(csu, sw, cop);

                                        sw.WriteLine();

                                        #endregion

                                        //Create Class Namespaces
                                        CodeNamespace testNameSpace = new CodeNamespace(Properties.Settings.Default.NAMESPACE);	

                                        DataGridViewRow dgvScenarioRow = new DataGridViewRow();
                                        int rowIndexS = dgv.Rows.Add(dgvScenarioRow);
                                        dgv.Rows[rowIndexS].Cells[0].Value = string.Format("\t Starting Generation of {0}..........................", scenario.TestCaseID);

                                        Console.WriteLine("\n\t{0} Starting Generation of {1}.............", thisDateTime, scenario.TestCaseID);
                                        File.AppendAllText(traceLogFileName, string.Format(Environment.NewLine + "\t{0} Starting Generation of {1}............." + Environment.NewLine, thisDateTime, scenario.TestCaseID));

                                        //Create Class Declaration
                                        CodeTypeDeclaration ctd = new CodeTypeDeclaration();
                                        ctd.IsClass = true;		
                                        ctd.Name = className;
                                        ctd.TypeAttributes = TypeAttributes.Public;

                                        CodeAttributeDeclaration attr = new CodeAttributeDeclaration("TestClass");
                                        

                                        ctd.CustomAttributes.Add(attr);
                                        ctd.BaseTypes.Add("TestBase");
                                        //sw.WriteLine();

                                        #region Generate Constructor
                                        CodeConstructor ccon = new CodeConstructor();
                                        ccon.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, "Constructor"));
                                        ccon.Parameters.Add(new CodeParameterDeclarationExpression("TestCaseStructure", "testContent"));
                                        ccon.Parameters.Add(new CodeParameterDeclarationExpression("ArrayList", "headerList"));
                                        ccon.Attributes = MemberAttributes.Public;
                                        //sw.Write("\t\t");
                                        ccon.Statements.Add(new CodeSnippetStatement("\t\t\ttestCaseStructure = testContent;"));
                                        //sw.Write("\t\t");
                                        ccon.Statements.Add(new CodeSnippetStatement("\t\t\theaderListBase = headerList;"));

                                        
                                        ccon.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, "End of Constructor"));
                                        
                                        ctd.Members.Add(ccon);

                                        testNameSpace.Types.Add(ctd);

                                        #endregion

                                        foreach (QAHelper.Common.TestScenario testScenario in testCaseStructure.TestScenarios)
                                        {
                                            #region Generate Test Methods

                                            attr = new CodeAttributeDeclaration("TestMethod");

                                            CodeMemberMethod cmm = new CodeMemberMethod();
                                            cmm.StartDirectives.Add(new CodeRegionDirective(CodeRegionMode.Start, testScenario.TestCaseID));
                                            cmm.Name = testScenario.TestCaseID;
                                            cmm.CustomAttributes.Add(attr);
                                            CodeVariableDeclarationStatement stmt = new CodeVariableDeclarationStatement(typeof(int), "noOfFields");
                                            stmt.InitExpression = new CodeSnippetExpression("0");
                                            cmm.Statements.Add(stmt);

                                            stmt = new CodeVariableDeclarationStatement(typeof(string), "result");
                                            stmt.InitExpression = new CodeSnippetExpression("string.Empty");
                                            cmm.Statements.Add(stmt);

                                            stmt = new CodeVariableDeclarationStatement(typeof(string), "actualResult");
                                            stmt.InitExpression = new CodeSnippetExpression("string.Empty");
                                            cmm.Statements.Add(stmt);

                                            CodeExpression[] expressions = { new CodeArgumentReferenceExpression("TestManager.browser"), 
                                                                             new CodeArgumentReferenceExpression("tempList"), 
                                                                             new CodeArgumentReferenceExpression("noOfFields") };

                                            
                                            CodeTypeReferenceExpression staticClass = new CodeTypeReferenceExpression(typeof(QAHelper.Common.WatiNInputHelper));
                                            
                                            CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(staticClass, "SetPageInput", expressions);

                                            cmm.Statements.Add(methodInvoke);

                                            sw.WriteLine();

                                            CodeConditionStatement condition = new CodeConditionStatement();
                                            condition.Condition = new CodeSnippetExpression("actualResult==scenario.ExpectedResult");
                                            condition.TrueStatements.Add(new CodeCommentStatement("result=\"Pass\";"));
                                            condition.FalseStatements.Add(new CodeCommentStatement("result=\"Faile\";"));

                                            cmm.Statements.Add(condition);

                                            cmm.EndDirectives.Add(new CodeRegionDirective(CodeRegionMode.End, testScenario.TestCaseID));
                                            cmm.Statements.Add(new CodeSnippetStatement("\t\t\ttestCaseStructure = QAHelper.Common.CommonHelper.UpdateTestCaseStructure(result, actualResult, testCaseStructure, scenario);"));
                                            ctd.Members.Add(cmm);

                                            #endregion
                                        }
                                        

                                        //Generate Source Code File
                                        cscg.GenerateCodeFromNamespace(testNameSpace, sw, cop);
                                        
                                        //Close StreamWriter
                                        sw.Close();
                                        s.Close();

                                        Console.WriteLine(" \t{0} End of Generation of {1}.............", thisDateTime, scenario.TestCaseID);
                                        File.AppendAllText(traceLogFileName, string.Format("\t{0} End of Execution of {1}............." + Environment.NewLine, thisDateTime, scenario.TestCaseID));
                                        dgvRow = UpdateDataGridView(dgv, dgvScenarioRow, rowIndexS,scenario.Status);
                                    }
                                }
                            }
                        }
                        dgvRow = UpdateDataGridView(dgv, testFileRow, rowIndex, "1");
                        dgvRow = UpdateDataGridView(dgv, dgvRow, rowIndexFiles, "1");

                        Console.WriteLine("{0} \nEnd of Generation of {1}.............", thisDateTime, className);
                        File.AppendAllText(traceLogFileName, string.Format(Environment.NewLine+"{0} End of Execution of {1}............." + Environment.NewLine, thisDateTime, className));
                        
                    }
                }
            }
            catch (Exception exp)
            {
                Console.WriteLine("{0} Unexpected error occurred. Error is:  {1}.............", thisDateTime, exp.Message);
                File.AppendAllText(traceLogFileName, string.Format("{0} Unexpected error occurred. Error is: {1}............." + Environment.NewLine, thisDateTime, exp.Message));
            }
            finally
            {

                Console.WriteLine("{0} End of Generating all test classes. Shutting down TestHarness for WatiN.............", thisDateTime);
                File.AppendAllText(traceLogFileName, string.Format("{0} End of Executing all test cases. Shutting down TestHarness for WatiN............." + Environment.NewLine, thisDateTime));
            }
        }

        private static DataGridViewRow UpdateDataGridView(DataGridView dgv, DataGridViewRow dgvRow, int rowIndex, string status)
        {
            if (status.Equals("Pass") || status.Equals("1"))
            {
                dgv.Rows[rowIndex].Cells[1].Value = Properties.Resources.tick;
                dgv.Rows[rowIndex].Cells[1].ToolTipText = "Pass";
            }
            else
            {
                dgv.Rows[rowIndex].Cells[1].Value = Properties.Resources.fail;
                dgv.Rows[rowIndex].Cells[1].ToolTipText = "Fail";
            }
            dgv.Refresh();
            dgvRow.Dispose();
            dgvRow = new DataGridViewRow();
            return dgvRow;

        }
    }    
}
